package com.wdb007.venus.svc.biz.manager;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.ServiceHelper;
import cn.jiguang.common.connection.NativeHttpClient;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.PushPayload.Builder;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;
import cn.jpush.api.push.model.notification.WinphoneNotification;

/**
 * 极光推送的接口类
 * @author lufeng
 *
 */
@Component("jPushManager")
public class JPushManager implements InitializingBean{
	private static String APP_KEY ;
	private static String MASTER_SECRET;
	private static String ALERT;
	private static Boolean APNSPRODUCTION;
	private static Logger logger = LoggerFactory.getLogger(JPushManager.class);
	
	@Autowired
	private ConfigInfoManager configInfoManager;
	
	/**
	 * 根据标签进行推送
	 */
	public void sendPushByTags(String[] tags) {
		ClientConfig clientConfig = ClientConfig.getInstance();
        final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        String authCode = ServiceHelper.getBasicAuthorization(APP_KEY, MASTER_SECRET);
        // Here you can use NativeHttpClient or NettyHttpClient or ApacheHttpClient.
        NativeHttpClient httpClient = new NativeHttpClient(authCode, null, clientConfig);
        // Call setHttpClient to set httpClient,
        // If you don't invoke this method, default httpClient will use NativeHttpClient.
        //ApacheHttpClient httpClient = new ApacheHttpClient(authCode, null, clientConfig);
        jpushClient.getPushClient().setHttpClient(httpClient);
        String[] tars = {"all"};
        final PushPayload payload = buildPushObject(JPushSendEnum.TAGS,tars,"这个是使用标签发送的测试内容");
//        // For push, all you need do is to build PushPayload object.
//        PushPayload payload = buildPushObject_all_alias_alert();
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            // 如果使用 NettyHttpClient，需要手动调用 close 方法退出进程
            // If uses NettyHttpClient, call close when finished sending request, otherwise process will not exit.
            // jpushClient.close();
        } catch (APIConnectionException e) {
        	logger.error("Connection error. Should retry later. ", e);
        	logger.error("Sendno: " + payload.getSendno());

        } catch (APIRequestException e) {
        	logger.error("Error response from JPush server. Should review and fix it. ", e);
        	logger.info("HTTP Status: " + e.getStatus());
        	logger.info("Error Code: " + e.getErrorCode());
        	logger.info("Error Message: " + e.getErrorMessage());
        	logger.info("Msg ID: " + e.getMsgId());
        	logger.error("Sendno: " + payload.getSendno());
        }
    }
	
	/**
	 * 根据用户注册Id来推送
	 */
	public void sendPushByRegistrationId(String[] registrationIds) {
		ClientConfig clientConfig = ClientConfig.getInstance();
		final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
        final PushPayload payload = buildPushObject(JPushSendEnum.REGISTRATIONID,registrationIds,"这个是使用id进行消息推送的测试");
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
            System.out.println(result);
        } catch (APIConnectionException e) {
        	logger.error("Connection error. Should retry later. ", e);
        	logger.error("Sendno: " + payload.getSendno());
        } catch (APIRequestException e) {
        	logger.error("Error response from JPush server. Should review and fix it. ", e);
        	logger.info("HTTP Status: " + e.getStatus());
        	logger.info("Error Code: " + e.getErrorCode());
        	logger.info("Error Message: " + e.getErrorMessage());
        	logger.info("Msg ID: " + e.getMsgId());
        	logger.error("Sendno: " + payload.getSendno());
        }
	}
	
	public void sendPushByRegistrationId(String[] registrationIds, Map message) {
		ClientConfig clientConfig = ClientConfig.getInstance();
		final JPushClient jpushClient = new JPushClient(MASTER_SECRET, APP_KEY, null, clientConfig);
		final PushPayload payload = buildPushObject_all_alert(JPushSendEnum.REGISTRATIONID,registrationIds,message);
        try {
            PushResult result = jpushClient.sendPush(payload);
            logger.info("Got result - " + result);
        } catch (APIConnectionException e) {
        	logger.error("Connection error. Should retry later. ", e);
        	logger.error("Sendno: " + payload.getSendno());
        } catch (APIRequestException e) {
        	logger.error("Error response from JPush server. Should review and fix it. ", e);
        	logger.info("HTTP Status: " + e.getStatus());
        	logger.info("Error Code: " + e.getErrorCode());
        	logger.info("Error Message: " + e.getErrorMessage());
        	logger.info("Msg ID: " + e.getMsgId());
        	logger.error("Sendno: " + payload.getSendno());
        }
	}
	
	/**
	 * 根据推送的类型（标签，registrationId）两种方式，组装通知的信息
	 * @return
	 */
	private PushPayload buildPushObject(JPushSendEnum jPushSendEnum,
			String[] strs, String message) {
		Builder builder = PushPayload.newBuilder();
		builder.setPlatform(Platform.all());
		if (jPushSendEnum.getId() == 1) {// 根据标签
			/**
			 * tag:数组。多个标签之间是 OR 的关系，即取并集。 
			 * tag_and:数组。多个标签之间是 AND 关系，即取交集。
			 * tag_not:数组。多个标签之间，先取多标签的并集，再对该结果取补集。 
			 * alias:数组。多个别名之间是 OR 关系，即取并集。
			 */
			builder.setAudience(Audience.tag(strs));
		} else if (jPushSendEnum.getId() == 2) {// 根据id
			builder.setAudience(Audience.registrationId(strs));
		}
		builder.setNotification(Notification.newBuilder()
				.addPlatformNotification(IosNotification.newBuilder()
				// alert：通知的内容在各个平台上，都可能只有这一个最基本的属性 "alert"。暂时无实际意义；上层有一个统一的Alert，这里会覆盖到
						.setAlert(ALERT)
						.setBadge(5)
						.setSound("happy")
//						.addExtra("from", "JPush")
						.build())
				.build());
//		builder.setMessage(Message.content(message));
		builder.setOptions(Options.newBuilder().setApnsProduction(false).build());
		return builder.build();
	}
	
	/**
	 * 根据推送的类型（标签，registrationId）两种方式，组装通知的信息
	 * @return
	 */
	private PushPayload buildPushObject(JPushSendEnum jPushSendEnum,
			String[] strs, Map message) {
		Builder builder = PushPayload.newBuilder();
		builder.setPlatform(Platform.all());
		if (jPushSendEnum.getId() == 1) {// 根据标签
			/**
			 * tag:数组。多个标签之间是 OR 的关系，即取并集。 
			 * tag_and:数组。多个标签之间是 AND 关系，即取交集。
			 * tag_not:数组。多个标签之间，先取多标签的并集，再对该结果取补集。 
			 * alias:数组。多个别名之间是 OR 关系，即取并集。
			 */
			builder.setAudience(Audience.tag(strs));
		} else if (jPushSendEnum.getId() == 2) {// 根据id
			builder.setAudience(Audience.registrationId(strs));
		}
		
		builder.setNotification(Notification.newBuilder()
				.addPlatformNotification(IosNotification.newBuilder()
				// alert：通知的内容在各个平台上，都可能只有这一个最基本的属性 "alert"。暂时无实际意义；上层有一个统一的Alert，这里会覆盖到
						.setAlert(ALERT)
						.setBadge(1)
						.setSound("happy")
//						.addExtra("from", "JPush")
						.addExtras(message)
						.build())
				.addPlatformNotification(AndroidNotification.newBuilder()
						.setAlert(ALERT)
						.addExtras(message)
						.build())
				.build());
//		builder.setMessage(Message.content(message));
		builder.setOptions(Options.newBuilder().setApnsProduction(false).build());
		return builder.build();
	}
	
	public PushPayload buildPushObject_all_alert(JPushSendEnum jPushSendEnum, String[] ids, Map message) {
		Audience audience = null ;
		if (jPushSendEnum.getId() == 1) {
			audience = Audience.tag(ids);
		}else {
			audience = Audience.registrationId(ids);
		}
		
		PushPayload ppload = PushPayload.newBuilder()
			.setPlatform(Platform.all())
//			.setAudience(Audience.all())
			.setAudience(audience)
			.setNotification(Notification.newBuilder()
					.addPlatformNotification(AndroidNotification.newBuilder()
							.setAlert(ALERT)
							.setTitle("worldbang")
							.setBuilderId(1)
							.addExtras(message)
							.build()
							)
					.addPlatformNotification(IosNotification.newBuilder()
							.setAlert(ALERT)
							.incrBadge(1)
							.setSound("happy")
							.addExtras(message)
							.build()
							)
					.addPlatformNotification(WinphoneNotification.newBuilder()
							.setAlert(ALERT)
							.setOpenPage("xxx.cs")
							.addExtras(message)
							.build()
							)
			.build()).setMessage(Message.newBuilder()
						.setMsgContent("worldbang")
						.setTitle("worldbang")
						.addExtras(message)
						.build()
					)
			.setOptions(Options.newBuilder()
					.setApnsProduction(true)
					.setSendno(1)
					.setTimeToLive(86400)
					.build()
					)
			.build();
			
		return ppload ;
	}
	
	public static void main(String[] args) {
		JPushManager jpush = new JPushManager();
//		String ids[] = {"18171adc03310b779c6"};
		String ids[] = {"18171adc0330eb7452d"};
//		String ids[] = {"100d8559097b6608178"};
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("push_type", "1");
		map.put("isbn", "9787543464636");
		map.put("bookname", "大卫,不可以!");
		jpush.sendPushByRegistrationId(ids, map);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		APP_KEY = configInfoManager.getValue("JPUSH_APP_KEY");
		MASTER_SECRET = configInfoManager.getValue("JPUSH_MASTER_SECRET");
		ALERT = configInfoManager.getValue("ALERT");//暂时无实际意义，各个推送平台可不一致
		APNSPRODUCTION = Boolean.valueOf(configInfoManager.getValue("APNSPRODUCTION"));	//线上测试标志:True, 线下测试标志:False
	}
}
